'use strict';

const Controller = require('egg').Controller;
const sharp = require('sharp')
const urlib = require("url")
const fetch = require('node-fetch')
const oss = require('../util/oss')
const uuid = require('node-uuid');
const fs = require('fs-extra');
const path = require("path")

class HomeController extends Controller {
    async index() {
        const {ctx, app, config} = this;
        const req = ctx.req
        const res = ctx.response
        ctx.logger.info(ctx.query)
        ctx.logger.info(ctx.config)
        var resultData = {}
        resultData.code = 200
        resultData.msg = "success"
        var width = ctx.query.width || 300
        var height = ctx.query.height || 300
        var url = ctx.query.url
        if (!url) {
            resultData.code = 400
            resultData.msg = "url can not be empty"
            res.status(400).json(resultData)
            return
        }
        var objectName = resolverObjectName(url)
        var smallImageObjectName = resolverSmallImageObjectName(objectName, width, height)
        var bucket = config.oss.defaultBucket
        let ossInfo = oss.getOssInfo(config, bucket)
        if (!ossInfo) {
            resultData.code = 400
            resultData.msg = "not know bucket"
            res.status(400).send(resultData)
            return
        }
        var smallImageObjectExist = await isExistObject(ossInfo.ossClient, smallImageObjectName)
        if (!smallImageObjectExist) {
            // 不存在，则压缩一张上传到oss中
            let tempFileDir = getTempDirPath(config)
            fs.ensureDirSync(tempFileDir)
            let imageName = urlib.parse(url).path.split("/").reverse()[0]
            let tempImageFile = tempFileDir + imageName
            var downloadSpan = ctx.tracer.startSpan('下载图片', {childOf: req.parentSpan});
            let downloadResult = await downloadImage(url, tempImageFile)
            downloadSpan.finish(req)
            var writeFileSpan = ctx.tracer.startSpan('写入图片到磁盘', {childOf: req.parentSpan});
            fs.writeFileSync(tempImageFile, downloadResult);
            writeFileSpan.finish(req)
            let smallFile = tempFileDir + uuid.v1() + path.parse(imageName).ext
            var resizeSpan = ctx.tracer.startSpan('压缩图片', {childOf: req.parentSpan});
            await new Promise(((resolve, reject) => {
                sharp(tempImageFile).resize(width, height, {kernel: sharp.kernel.nearest}).toFile(smallFile, (err, info) => {
                    resizeSpan.finish(req)
                    if (!err) {
                        resolve(info)
                    } else {
                        reject(err)
                    }
                })
            }))
            var uploadFileSpan = ctx.tracer.startSpan('上传图片', {childOf: req.parentSpan});
            await ossInfo.ossClient.multipartUpload(smallImageObjectName, smallFile);
            uploadFileSpan.finish(req)
            fs.removeSync(tempFileDir)
        }
        res.redirect(ossInfo.ossConfig.ossDomainName + "/" + smallImageObjectName)
        return
    }
}


async function isExistObject(ossclient, name, options = {}) {
    try {
        await ossclient.head(name, options);
        console.log('文件存在')
        return true
    } catch (error) {
        if (error.code === 'NoSuchKey') {
            console.log('文件不存在')
        }
        return false
    }
}

function getTempDirPath(config) {
    var now = new Date()
    var year = now.getFullYear()
    var month = now.getMonth() + 1
    var day = now.getDate()
    var hour = now.getHours()
    return config.server.tempDir + "/" + year + "/" + month + "/" + day + "/" + hour + "/" + uuid.v1() + "/"
}

// 解析出objectName
function resolverObjectName(url) {
    return urlib.parse(url).path.substring(1)
}

// 计算出小图objectName
function resolverSmallImageObjectName(objectName, width, height) {
    return objectName + "_" + width + "_" + height
}

async function downloadImage(url) {
    const res = await fetch(url, {
        method: 'GET',
        headers: {'Content-Type': 'application/octet-stream'},
    });
    const result = await res.buffer();

    return result;
}

module.exports = HomeController;
